#ifndef FD_LIST_H_
#define FD_LIST_H_
#include <stdbool.h>
#include "bstrlib.h"

typedef struct sfd_item *fd_item;

typedef struct sfd_list *fd_list;

/*
    Devuelve un item vacio
*/
fd_item
fd_item_create(void);

/*
    Permite setear el numero de fd del item
*/
void
fd_item_set_fd(fd_item item, int fd);

/*
    Obtenemos el fd
*/
int
fd_item_get_fd(fd_item item);

/*
    Funcion para setear el valor del campo command:
    0:hello
    1:get_file_listing
    2:get_sources
    3:get_metadata
    4:new_fragment
    5:get_slice
    6:quit
*/
void
fd_item_set_cmd(fd_item item, int cmd);

/*
    Obtenemos el comando con el que esta seteado el fd
*/
int
fd_item_get_cmd(fd_item item);

/*
    Funcion para setear el numero de archivo que estoy bajando
*/
void
fd_item_set_file_n(fd_item item, int file_n);

/*
    Funcion para obtener el numero de archivo que estoy bajando
*/
int
fd_item_get_file_n(fd_item item);

/*
    Funcion para setear el numero de parte que estoy bajando
*/
void
fd_item_set_part_n(fd_item item, int part_n);

/*
    Funcion para obtener el numero de parte que estoy bajando
*/
int
fd_item_get_part_n(fd_item item);

/*
    Funcion para setear cuantas partes me faltan
*/
void
fd_item_set_cant(fd_item item, int cant);

/*
    Funcion para obtener cuantas partes me faltan
*/
int
fd_item_get_cant(fd_item item);

/*
    Funcion para setear el codigo de respuesta
*/
void
fd_item_set_answ(fd_item item, int answ);

/*
    Funcion para obtener el codigo de respuesta
*/
int
fd_item_get_answ(fd_item item);

/*
    Funcion para anunciar que ya termine de recibir
*/
void
fd_item_finished_receiving(fd_item item);

/*
    Funcion para anunciar que no terminé de recibir
*/
void
fd_item_not_finished_receiving(fd_item item);

/*
    Funcion para preguntar si termine de recibir
*/
bool
fd_item_has_finished_receiving(fd_item item);

/*
    Funcion para anunciar que ya termine de atender el nodo
*/
void
fd_item_finished_attending(fd_item item);

/*
    Funcion para anunciar que no terminé de atender el nodo
*/
void
fd_item_not_finished_attending(fd_item item);

/*
    Funcion para preguntar si termine de atender el nodo
*/
bool
fd_item_has_finished_attending(fd_item item);

/*
    Funcion para anunciar que estoy enviando
*/
void
fd_item_sending(fd_item item);

/*
    Funcion para anunciar que estoy recibiendo
*/
void
fd_item_receiving(fd_item item);

/*
    Funcion para preguntar si estoy enviando
*/
bool
fd_item_am_i_sending(fd_item item);


/*
    Funcion para anunciar que es el tracker
*/
void
fd_item_index(fd_item item);

/*
    Funcion para anunciar que no es un tracker
*/
void
fd_item_not_index(fd_item item);

/*
    Funcion para preguntar si es un tracker
*/
bool
fd_item_is_tracker(fd_item item);

/*
    Funcion para anunciar que es un peer
*/
void
fd_item_peer(fd_item item);

/*
    Funcion para anunciar que no es un peer
*/
void
fd_item_not_peer(fd_item item);

/*
    Funcion para preguntar si es un peer
*/
bool
fd_item_is_peer(fd_item item);

/*
    Funcion para eliminar el contenido de
    recv_buf
*/
void
fd_item_clear_data(fd_item item);

/*
    Funcion para setear el campo recv_buf
    Devuelve 1 en caso de exito 0 en caso de error
*/
void
fd_item_set_data(fd_item item, bstring data);

/*
    Funcion para obtener el campo recv_buf
*/
bstring
fd_item_get_data(fd_item item);

/*
    Funcion para setear el campo ip_port
    Devuelve 1 en caso de exito 0 en caso de error
*/
int
fd_item_set_ip_port(fd_item item, char* ip_port);

/*
    Funcion para obtener el campo ip_port
*/
char*
fd_item_get_ip_port(fd_item item);

/*
    Seteamos el offset del archivo pedido
*/
void
fd_item_set_offset(fd_item item, int offset);

/*
    Obtenemos el offset pedido
*/
int
fd_item_get_offset(fd_item item);

/*
    Seteamos el amount pedido
*/
void
fd_item_set_amount(fd_item item, int amount);

/*
    Obetenemos el amount pedido
*/

int
fd_item_get_amount(fd_item item);

/*
    Aca vamos cargando cuanto ya le hemos enviado al cliente
*/
void
fd_item_set_transferred(fd_item item, int transferred);

/*
    Obtenemos informacion sobre cuanto hemos enviado al cliente
*/

int
fd_item_get_transferred(fd_item item);

/*
    Este es el destructor
*/
void
fd_item_destroy(fd_item item);

/*
    ACA EMPIEZAN LAS FUNCIONES DE LISTA
*/

/*
    Constructor de lista
*/
fd_list
fd_list_create(void);

/*
    Aqui vamos agregando items a la lista de fd's
    le pasamos el fd, y el comando pedido, el fd es cargado
    en el ultimo lugar de la lista
*/
void
fd_list_add_fd(fd_list list, int fd);

/*
    Obtenemos el fd
*/
int
fd_list_get_fd(fd_list list, int n);

/*
    Seteamos el comando para el fd
*/
void
fd_list_set_cmd(fd_list list, int n, int cmd);

/*
    Obetenemos el comando con el que fue seteado el fd
*/
int
fd_list_get_cmd(fd_list list, int n);

/*
    Seteo el numero de archivo que estoy bajando
*/
void
fd_list_set_file_n(fd_list list, int n, int i);

/*
    Pido el numero de archivo que estoy bajando
*/
int
fd_list_get_file_n(fd_list list, int n);

/*
    Seteo el numero de parte que estoy bajando
*/
void
fd_list_set_part_n(fd_list list, int n, int i);

/*
    Pido el numero de parte que estoy bajando
*/
int
fd_list_get_part_n(fd_list list, int n);

/*
    Seteo la cantidad de partes que me faltan de bajar de aca
*/
void
fd_list_set_cant(fd_list list, int n, int i);

/*
    Pido la cantidad de partes que me faltan bajar de aca
*/
int
fd_list_get_cant(fd_list list, int n);

/*
    Funcion para setear el codigo de respuesta
*/
void
fd_list_set_answ(fd_list list, int n, int i);

/*
    Pido el codigo de respuesta del item en n
*/
int
fd_list_get_answ(fd_list list, int n);

/*
 	Anunciamos que terminamos de recibir de aca
*/
void
fd_list_finished_receiving(fd_list list, int n);

/*
 	Anunciamos qu eno terminamos de recibir todavia
*/
void
fd_list_not_finished_receiving(fd_list list, int n);

/*
 	Preguntamos si terminamos de recibir
*/
bool
fd_list_has_finished_receiving(fd_list list, int n);

/*
    Anunciamos que terminamos de atender el item ubicado en n
*/
void
fd_list_finished_attending(fd_list list, int n);

/*
    Anunciamos que no terminamos de atender el item ubicado en n
*/
void
fd_list_not_finished_attending(fd_list list, int n);

/*
    Preguntamos si termine de atender el item ubicado en n
*/
bool
fd_list_has_finished_attending(fd_list list, int n);

/*
    Anunciamos que estoy enviandole a este item
*/
void
fd_list_sending(fd_list list, int n);

/*
    Anunciamos que estoy recibiendo desde este item
*/
void
fd_list_receiving(fd_list list, int n);

/*
    Pregunto si estoy enviando a este item
*/
bool
fd_list_am_i_sending(fd_list list, int n);

/*
 	Informo que este item es un tracker
*/
void
fd_list_index(fd_list list, int n);

/*
 	Informo que este item no es un tracker
*/
void
fd_list_not_index(fd_list list, int n);

/*
   Pregunto si este item es un tracker
*/
bool
fd_list_is_index(fd_list list, int n);

/*
 	Informo que este item es un peer
*/
void
fd_list_peer(fd_list list, int n);

/*
 	Informo que este item no es un peer
*/
void
fd_list_not_peer(fd_list list, int n);

/*
 	Pregunto si este item es un peer
*/
bool
fd_list_is_peer(fd_list list, int n);

/*
    Funcion para eliminar el contenido del data del item n
*/
void
fd_list_clear_data(fd_list list, int n);

/*
 	Seteo el campo recv_buf del item
*/
void
fd_list_set_data(fd_list list, int n, bstring data);

/*
    Funcion para obtener el campo recv_buf
*/
bstring
fd_list_get_data(fd_list list, int n);

/*
    Funcion para setear el campo ip_port
    Devuelve 1 en caso de exito 0 en caso de error
*/
int
fd_list_set_ip_port(fd_list list, int n, char* ip_port);

/*
    Funcion para obtener el campo ip_port
*/
char*
fd_list_get_ip_port(fd_list list, int n);

/*
  Obtenemos el offset pedido en el fd ubicado en la posicion n de la lista
*/
int
fd_list_get_offset(fd_list list, int n);

/*
  Seteamos el offset en el fd ubicado en la posicion n de la lista
*/
void
fd_list_set_offset(fd_list list, int n, int m);

/*
  Obtenemos el amount del fd ubicado en la posicion n de la lista
*/
int
fd_list_get_amount(fd_list list, int n);

/*
  Seteamos el amount en el fd ubicado en la posicion n de la lista
*/
void
fd_list_set_amount(fd_list list, int n, int m);

/*
    Con esta funcion sacamos el elemento n de la lista
*/
void
fd_list_remove(fd_list list, int n);

/*
    Con esta funcion devolvemos la ubicacion en la lista
    de un fd
*/
int
fd_list_search(fd_list list, int fd);

/*
    Obtenemos el item con indice n
*/
fd_item
fd_list_get_item(fd_list list, int n);

/*
  Obtenemos el numero de fd's en la lista (tamaño de la lista)
*/
int
fd_list_size(fd_list list);

/*
  Seteamos la cantidad transferida del archivo en el fd ubicado
  en la posicion n de la lista
*/
void
fd_list_set_transferred(fd_list list, int n, int transferred);

/*
  Obtenemos la cantidad transferida del archivo en el fd ubicado
  en la posicion n de la lista
*/
int
fd_list_get_transferred(fd_list list, int n);

/*
  Destructor del tipo fd_list
*/
void
fd_list_destroy(fd_list list);

#endif /*FD_LIST_H_*/
